package top.xx252016.coreClient.clientChat;

import top.xx252016.coreClient.base.Contract;
import top.xx252016.coreClient.base.NodeClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.nio.charset.Charset;

/*
 .广域网模式...
 .局域网模式...
 .本地服务端...
 */
public class ChatClientMain {

    static Contract.AppContract mContract;
    private String msgAdmin = "";
    private String hosts[] = "127.0.0.1,www.xx252016.top,192.168.0.1".split(",");
    private Integer server_port = 55555;
    private NodeClient clientNode = null;

    private static class ChatClientInstance {
        private final static ChatClientMain instance = new ChatClientMain();
    }

    public void setAppContract(Contract.AppContract contract) {
        mContract = contract;
    }

    public void send2Socket(String content) throws IOException {
        /* 当前线程发送消息 */
        clientNode.getOos().writeUTF(content);
        clientNode.getOos().flush();
    }

    public void quit(){
        clientNode.setLoginS("false");
    }

    public NodeClient getClientNode() {
        return clientNode;
    }

    private boolean judgeOline(NodeClient client) {
        return "true".endsWith(client.getLoginS());
    }

    private boolean judgeTrmlAndroid(NodeClient client) {
        return "Android".endsWith(client.getLoginT());
    }

    private boolean doOffLine() {

        return true;
    }

    public void changeTrml(String trml) {
        this.clientNode.setLoginT(trml);
    }

    public void clientMain() {
        /* 生成新节点 */
        clientNode = new NodeClient();
        /*登录状态*/
        clientNode.setLoginS("false");
        /*登录终端*/
        clientNode.setLoginT("pc");
    }

    private void sendImpl(String content) {
        try {
            send2Socket(content);
        } catch (IOException e) {
            msgAdmin = "...getServerSocket exception...";
            System.out.println("send2Socket>>>" + msgAdmin);
        }
    }

    /*连接服务器,获取socket.>>>主程*/
    /*在线则死循环维持soket连接*/
    /*在线标记置否关闭sokect*/
    public void doJoin() {
        NodeClient clientNode = doLink();
        /*客户端字符集*/
        String cc = Charset.defaultCharset().displayName();
        /*告知服务器客户端字符集*/
        clientNode.setClientCharset(cc);
        msgAdmin = "ccc" + cc;
        sendImpl(msgAdmin);
        BufferedReader sbr;
        if (null == clientNode.getServerSocket()) {
            System.out.println("无可用服务,稍后再试...");
            clientNode.setLoginS("false");
        }
        /* 设置当前窗口属性 */
        // new OrderThread("color 31", cs).start();
        // new OrderThread("title '*聊天室*'", cs).start();
        // new Thread(new OrderThread("dir", cs)).start();
        // Desktop.getDesktop().open();
        sbr = new BufferedReader(new InputStreamReader(System.in));
        while (judgeOline(clientNode)) {
            if (judgeTrmlAndroid(clientNode)) {
                /*android*/
                break;
            } else if ("swing".equals(clientNode.getLoginT())) {
                /*swing*/
                break;
            } else if (!judgeTrmlAndroid(clientNode)) {
                try {
                    msgAdmin = sbr.readLine();
                    if (null == msgAdmin || "".equals(msgAdmin)) {
                        System.out.println("无效输入");
                    } else if (msgAdmin.startsWith("eof")) {
                        clientNode.setLoginS("false");
                    } else {
                        /* 信息写入.刷新内存.数据立即写出 */
                        sendImpl(msgAdmin);
                    }
                } catch (Exception e) {
                    System.out.println("catch→" + e.toString());
                    /* 当前线程发送消息 */
                    msgAdmin = "...ending with catch exception..." + e.getMessage();
                    clientNode.setLoginS("false" + msgAdmin);
                    System.out.println("send2Socket>>>" + msgAdmin);
                }
            } else {
                System.out.println(" 终端标识异常");
            }
        }
        System.out.println(" doJoin 之后");
        /*...*/
    }

    /*连接服务器,获取socket.>>>收信线程*/
    private NodeClient doLink() {
        /*获取socket连接*/
        Socket socket = null;
        /* 创建Socket对象,与服务器建立通信 */
        for (int i = 0; i < hosts.length; i++) {
            msgAdmin = "";
            try {
                socket = new Socket(hosts[i], server_port);
                if (null != socket) {
                    clientNode.setServerSocket(socket);
                    clientNode.setOis(new ObjectInputStream(socket.getInputStream()));
                    clientNode.setOos(new ObjectOutputStream(socket.getOutputStream()));
                    /*标记用户为登录状态*/
                    clientNode.setLoginS("true");
                    /* 启动收信线程 */
                    new ChatClientMessageReceive(this).start();
                    msgAdmin = ">连接成功>>>";
                    /*跳出循环*/
                    break;
                }
            } catch (Exception e) {
                /* 客户端获取socket异常 */
                msgAdmin = ">连接失败>>>";
            } finally {
                System.out.println(hosts[i] + msgAdmin);
            }
        }
        return clientNode;
    }

    public static ChatClientMain getInstance() {
        return ChatClientInstance.instance;
    }

    /* 私有内部类 */
    @SuppressWarnings("unused")
    private class Invalid {

    }

    public static void main(String[] args) {
        ChatClientMain clientMain = ChatClientMain.getInstance();
        clientMain.clientMain();
        clientMain.doJoin();
        System.out.println("[main]" + "start CcSs");
    }
}

/*收信线程*/
class ChatClientMessageReceive extends Thread {
    ChatClientMain instance;
    NodeClient node;

    public ChatClientMessageReceive(ChatClientMain instance) {
        this.instance = instance;
        this.node = instance.getClientNode();
    }

    @Override
    public void run() {
        ObjectInputStream ois = instance.getClientNode().getOis();
        String message = "";
        try {
            /* 循环读取 */
            while ("true".equals(instance.getClientNode().getLoginS())) {
                message = ois.readUTF();
                /* 读取数据是否为空 */
                if (null == message) {
                    continue;
                } else {
                    /*判断终端类型,调用对应接口*/
                    if ("Android".equals(node.getLoginT()) && "true".equals(node.getLoginS())) {
                        ChatClientMain.mContract.readFromSocket(message);
                    }
                    if ("swing".equals(node.getLoginT()) && "true".equals(node.getLoginS())) {
                        ChatClientMain.mContract.readFromSocket(message);
                    }
                    if (message.startsWith("order") && "true".equals(node.getLoginS())) {
                        message = message.replace("order", "");
                        System.out.println("→" + node.getClientCharset());
                        new Thread(new OrderThread(message, node.getClientCharset())).start();
                        continue;
                    }
                    System.out.println("[smr]" + message);
                }
            }
            /* 客户端主动关闭连接 */
            node.setLoginS("false");
            message = "end with close itself";
            /*下线关闭soket*/
            try {
                node.getServerSocket().close();
            } catch (IOException e) {
                System.out.println("skt close except" + e.toString());
            }
            System.out.println(message);
        } catch (IOException e) {
            /* 线程结束 */
            System.out.println("与服务器失去连接..." + e.toString());
            //System.exit(0);
        }
    }
}

class OrderThread implements Runnable {
    private String order;
    private String charset;
    private InputStreamReader isr;

    public OrderThread(String order, String charset) {
        this.order = order;
        this.charset = charset;
    }

    @Override
    public void run() {
        String str_res = "", str_tem = "";
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(order);
            isr = new InputStreamReader(process.getInputStream(), charset);
            BufferedReader br = new BufferedReader(isr);
            /* UTF-8,GBK */
            while ((str_tem = br.readLine()) != null) {
                str_res += str_tem + "\n";
            }
        } catch (IOException e) {
            /*修改客户端字符集等属性*/
            System.out.println("客户端窗口属性设置失败");
        } finally {
            if (null != process) {
                process.destroy();
            }
        }
        str_res = "[smo]<" + order + ">-->\n\t" + str_res;
        System.out.println(str_res);
    }
}
